package com.ruoyi.electronicFence.task;

import com.ruoyi.common.AgreementAnalysis;
import com.ruoyi.common.AsyncTcpServer;
import com.ruoyi.common.DataConversion.domain.AgreementAnalysisV2;
import com.ruoyi.common.GenericMethods;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.domin.MainObject;
import com.ruoyi.electronicFence.domain.ReceiveEFData;
import com.ruoyi.electronicFence.domain.TDeviceStatus;
import com.ruoyi.electronicFence.service.ITDeviceStatusService;
import com.ruoyi.electronicFence.service.ITEfAlarmService;
import kong.unirest.HttpResponse;
import kong.unirest.Unirest;
import kong.unirest.UnirestException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

import java.util.List;
import java.util.Map;
import java.util.concurrent.*;


@Component
public class DeviceMonitor {

    @Value("${system.name}")
    String SYSTEM_NAME;

    @Value("${system.tcpServiceIp}")
    String SYSTEM_TCPSERVICEIP;

    @Value("${system.tcpServicePort}")
    Integer SYSTEM_TCPSERVICEPORT;

    @Value("${system.transport_protocol}")
    String SYSTEM_TRANSPORT_PROTOCOL;

    @Value("${scheduler.receiveAlarmDataUpdateCron}")
    private String initialMonitorStatusUpdateCron;

    @Autowired
    private  AgreementAnalysis agreementAnalysis;

    @Autowired
    private AgreementAnalysisV2 agreementAnalysis2;


    private final ITDeviceStatusService iTDeviceStatusService;
    private final ITEfAlarmService iTEfAlarmService;
    private ExecutorService executor;
    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd%20HH:mm:ss");
    @Autowired
    public DeviceMonitor(ITDeviceStatusService iTDeviceStatusService, ITEfAlarmService iTEfAlarmService) {
        this.iTDeviceStatusService = iTDeviceStatusService;
        this.iTEfAlarmService = iTEfAlarmService;
    }

//    @PostConstruct
    public void startMonitoring() {
        try {
            // 获取设备状态列表
            TDeviceStatus deviceStatus1 = new TDeviceStatus();
            deviceStatus1.setDeviceStatus("在线");
            List<TDeviceStatus> initialDeviceStatuses = iTDeviceStatusService.selectTDeviceStatusList(deviceStatus1);
            int deviceCount = initialDeviceStatuses.size();

            // 创建一个固定大小的线程池
            executor = Executors.newFixedThreadPool(4);

            // 创建任务并提交到线程池
            executor.execute(() -> {
                while (!Thread.currentThread().isInterrupted()) {
                    try {
                        // 获取设备状态列表
                        TDeviceStatus deviceStatus2 = new TDeviceStatus();
                        deviceStatus2.setDeviceStatus("在线");
                        List<TDeviceStatus> tDeviceStatuses = iTDeviceStatusService.selectTDeviceStatusList(deviceStatus2);

                        for (TDeviceStatus deviceStatus : tDeviceStatuses) {
                            final String deviceId = deviceStatus.getDeviceId();
                            final String deviceIp = deviceStatus.getDeviceIp();

                            // 提交任务到线程池
                            executor.submit(() -> {
                                try {
                                    // 每次循环开始前等待一秒
                                    Thread.sleep(5000); // 确保每秒一次请求
                                    // 获取当前时间
                                    LocalDateTime now = LocalDateTime.now();

                                    System.out.println("电子围栏系统-实时监测设备状态："+now);

                                    // 构建设备的具体URL
                                    String urlString = "http://" + deviceIp + ":8080/electronicFence/receive-alarm-data?dataTime=" + now.format(FORMATTER);
                                    URL url = new URL(urlString);

                                    // 发送 GET 请求并获取响应
                                    HttpResponse<String> response = Unirest.get(url.toExternalForm())
                                            .header("Content-Type", "application/json")
                                            .header("Accept", "*/*")
                                            .header("Host", deviceIp)
                                            .header("Connection", "keep-alive")
                                            .connectTimeout(5000)  // 设置连接超时时间
                                            .socketTimeout(5000)   // 设置读取超时时间
                                            .asString();

                                    if (response.getStatus() == 200) {
                                        // 输出设备的状态信息
//                                        System.out.println("Device " + deviceId + " status: " + response.getBody());
                                        String body = response.getBody();
                                        updateDeviceStatus(body);
                                    } else {
                                        System.err.println("Failed to get status for device " + deviceId + ". Status code: " + response.getStatus());
                                    }

                                    // 模拟等待，如果服务器没有立即返回响应，则等待
                                    Thread.sleep(1000); // 1秒
                                } catch (MalformedURLException | UnirestException | InterruptedException e) {
                                    // 处理异常
                                    e.printStackTrace();
                                }
                            });
                        }

                        // 等待一定时间再重新获取设备状态列表
                        Thread.sleep(1000); // 5秒
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Scheduled(cron = "*/5 * * * * *") // 每5秒执行一次
    public void startMonitoringV2()  {
        //当 系统名称为电子围栏 且 支持HTTP协议 进行数据获取
        if (SYSTEM_NAME.equals("ef") && SYSTEM_TRANSPORT_PROTOCOL.contains("HTTP")){
            try {
                // 获取设备状态列表
                TDeviceStatus deviceStatus = new TDeviceStatus();
                deviceStatus.setDeviceStatus("在线");
                deviceStatus.setTransportProtocol("HTTP");
                List<TDeviceStatus> tDeviceStatuses = iTDeviceStatusService.selectTDeviceStatusList(deviceStatus);

                // 遍历设备列表并异步发送请求
                for (TDeviceStatus deviceStatusItem : tDeviceStatuses) {
                    final String deviceId = deviceStatusItem.getDeviceId();
                    final String deviceIp = deviceStatusItem.getDeviceIp();


                    CompletableFuture.runAsync(() -> {

                        if (pingDevice(deviceIp)){
                            try {


                                // 获取当前时间
                                LocalDateTime now = LocalDateTime.now();
//                        System.out.println("电子围栏系统-实时监测设备状态：" + now);
                                // 构建设备的具体URL
                                String urlString = "http://" + deviceIp + ":8080/electronicFence/receive-alarm-data?dataTime=" + now.format(FORMATTER);
                                URL url = new URL(urlString);
                                // 发送 GET 请求并获取响应
                                HttpResponse<String> response = Unirest.get(url.toExternalForm())
                                        .header("Content-Type", "application/json")
                                        .header("Accept", "*/*")
                                        .header("Host", deviceIp)
                                        .header("Connection", "keep-alive")
                                        .connectTimeout(5000)  // 设置连接超时时间
                                        .socketTimeout(5000)   // 设置读取超时时间
                                        .asString();

                                if (response.getStatus() == 200) {
                                    // 输出设备的状态信息
                                    String body = response.getBody();
                                    updateDeviceStatus(body);
                                } else {
                                    System.err.println("Failed to get status for device " + deviceId + ". Status code: " + response.getStatus());
                                }

                                // 模拟等待，如果服务器没有立即返回响应，则等待
                                Thread.sleep(1000); // 1秒
                            } catch (MalformedURLException | UnirestException | InterruptedException e) {
                                // 处理异常

                                GenericMethods.logError(e);
                            }
                        }else {
                            System.out.println(deviceIp+"该设备离线");
                        }

                    });
                }
            } catch (Exception e) {
                GenericMethods.logError(e);
            }
        }

    }

    private ScheduledExecutorService scheduler;


    // 示例方法：获取设备ID列表（需要根据实际情况实现）
    public void sendRequest(TDeviceStatus device) {
        try {// 每次循环开始前等待一秒



            Thread.sleep(5000); // 确保每秒一次请求
            // 获取当前时间
            LocalDateTime now = LocalDateTime.now();

            System.out.println("电子围栏系统-实时监测设备状态："+now);
            String deviceIp = device.getDeviceIp();
            String deviceId = device.getDeviceId();
            // 构建设备的具体URL
            String urlString = "http://" + deviceIp + ":8080/electronicFence/receive-alarm-data?dataTime=" + now.format(FORMATTER);
            try {
                URL url = new URL(urlString);
                // 发送 GET 请求并获取响应
                HttpResponse<String> response = Unirest.get(url.toExternalForm())
                        .header("Content-Type", "application/json")
                        .header("Accept", "*/*")
                        .header("Host", deviceIp)
                        .header("Connection", "keep-alive")
                        .connectTimeout(5000)  // 设置连接超时时间
                        .socketTimeout(5000)   // 设置读取超时时间
                        .asString();

                if (response.getStatus() == 200) {
                    // 输出设备的状态信息
//                                        System.out.println("Device " + deviceId + " status: " + response.getBody());
                    String body = response.getBody();
                    updateDeviceStatus(body);
                } else {
                    System.err.println("Failed to get status for device " + deviceId + ". Status code: " + response.getStatus());

                }
//            updateDeviceOnlineStatus(response.getStatus(),device);
                // 模拟等待，如果服务器没有立即返回响应，则等待
                Thread.sleep(1000); // 1秒
            }
            catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }


        }catch (Exception e){

        }



    }

    private void updateDeviceOnlineStatus(int status,TDeviceStatus device) {
        device.setUpdateTime(LocalDateTime.now());

        if (status==200){
            device.setDeviceStatus("在线");

        }else {
            device.setDeviceStatus("离线");
        }
        AjaxResult ajaxResult = iTDeviceStatusService.updateTDeviceStatus(device);
//        ajaxResult.get("")
//        if (i>0){
//            System.out.println("监测设备状态更新成功");
//        }

    }


    @PreDestroy
    public void stopMonitoring() {
        if (executor != null) {
            executor.shutdown();
            try {
                if (!executor.awaitTermination(5, java.util.concurrent.TimeUnit.SECONDS)) {
                    executor.shutdownNow();
                }
            } catch (InterruptedException e) {
                executor.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }

    public void updateDeviceStatus(String body) {
        JSONObject jsonObject = new JSONObject(body);
        // 进行数据转换入库dataConversion
        Map<String, Object> map = jsonObject.toMap();
        dataConversion(map);
    }

    public void updateDeviceStatusOffline(String deviceIp) {
        AjaxResult ajaxResult = new AjaxResult();

        // new 接收报警数据对象
        ReceiveEFData receiveEFData = new ReceiveEFData();
        receiveEFData.setControllerIP(deviceIp);
        receiveEFData.setAlarmTime(LocalDateTime.now());
//        receiveEFData.setEquipmentStatus("3");
        receiveEFData.setControllerStatus("3");
        int i = iTEfAlarmService.InboundDataOftAlarm(receiveEFData);
        if (i > 0) {
            ajaxResult.isSuccess();
            ajaxResult.put("code", 200);
            ajaxResult.put("msg", "入库成功");
        }
    }

    /**
     * 接收电子围栏报警数据的接口。
     *
     * @param map 包含报警数据的Map对象，具体字段如下：
     *            - dataTime (String): 报警数据的时间戳，格式为 "yyyy-MM-dd HH:mm:ss"。
     *            - equipmentStatus (String): 设备状态，取值范围如下：
     *                - 0: 运行
     *                - 1: 停机
     *                - 2: 未接入
     *            - controllerIP (String): 控制器的IP地址。
     *            - controllerStatus (String): 控制器状态，取值范围如下：
     *                - 0: 正常
     *                - 1: 预警
     *                - 2: 断电
     *                - 3: 离线
     *            - alarmTime (String): 报警时间，格式为 "yyyy-MM-dd HH:mm:ss"。
     *            - alarmType (List<String>): 报警类型列表，取值范围如下：
     *                - 0: UWB
     *                - 1: 热释电
     *                - 2: AI识别
     *            - personCardInfo (Map<String, Object>): UWB人员定位卡信息。
     *            - pictureUrl (String): 告警图片的URL地址。
     *
     *             * 示例请求URL:
     *  * http://192.168.3.43:8080/electronicFence/receive-alarm-data
     *  * ?dataTime=2024-05-28%2008:56:14
     *
     * @return 返回操作结果，成功时返回受影响的记录数，失败时返回0或其他错误码。
     * @param map
     * @return
     */

    public AjaxResult dataConversion(Map<String, Object> map) {

        AjaxResult ajaxResult = new AjaxResult();
        // 如果响应成功 则向报警数据存数
        if ("Succeed".equals(map.get("Result"))) {
            // new 接收报警数据对象
            ReceiveEFData receiveEFData = new ReceiveEFData();
            // 解析控制器类型
            // 获取当前本地时间
//            LocalDateTime now = LocalDateTime.now();
//            int second = now.getSecond();
//            System.out.println(second);

            String controllerStatus = (String) map.get("controllerStatus");

            receiveEFData.setControllerStatus(controllerStatus);
//            receiveEFData.setControllerStatus("2");

            // 解析时间
            String alarmTime = (String) map.get("alarmTime");
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime alarmDateTime = LocalDateTime.parse(alarmTime, formatter);
            receiveEFData.setAlarmTime(alarmDateTime);
            // 解析IP
            String controllerIP = (String) map.get("controllerIP");
            receiveEFData.setControllerIP(controllerIP);

            if (map.get("equipmentStatus")!=null){
                String equipmentStatus = (String) map.get("equipmentStatus");
            }


            if (map.get("pictureUrl")!=null){
                String pictureUrl = (String) map.get("pictureUrl");
                receiveEFData.setPictureUrl(pictureUrl);
            }

            // 获取并检查 "apeIP" 的值
            Object apeIPObject = map.get("apeIP");

            if (apeIPObject instanceof String) {
                String apeIP = (String) apeIPObject;

                // 检查是否为空字符串
                if (!apeIP.trim().isEmpty()) {
                    try {
                        // 将 IP 地址转换为数值，并设置到 receiveEFData 中
                        String apeID = GenericMethods.convertIpToNumeric(apeIP);
                        receiveEFData.setApeId(Integer.parseInt(apeID));
                    } catch (NumberFormatException e) {
                        // 处理转换失败的情况
                        System.err.println("Invalid IP format: " + apeIP);
                        // 可以选择抛出异常或采取其他措施
                    }
                }
            }

            // 获取并检查 "apeName" 的值
            if (map.get("apeName")!=null)
          {
                String apeName = (String) map.get("apeName");

                // 检查是否为空字符串
                if (!apeName.trim().isEmpty()) {
                    try {
                        receiveEFData.setApeName(apeName);
                    } catch (NumberFormatException e) {
                        // 处理转换失败的情况
                        System.err.println("Invalid apeName format: " + apeName);
                        // 可以选择抛出异常或采取其他措施
                    }
                }
            }




            Object value = map.get("alarmType");
            String[] alarmType = new String[0];
            if (value != null && value instanceof String[]) {
                alarmType = (String[]) value;
            }
            receiveEFData.setAlarmType(alarmType);
            if (map.get("personCardInfo")!=null){
                Map<String, List<Map<String, Object>>> personCardInfoMap = (Map<String, List<Map<String, Object>>>) map.get("personCardInfo");
                receiveEFData.setPersonCardInfoMap(personCardInfoMap);
            }


            int i = iTEfAlarmService.InboundDataOftAlarmV2(receiveEFData);
            if (i > 0) {
                ajaxResult.isSuccess();
                ajaxResult.put("code", 200);
                ajaxResult.put("msg", "入库成功");
            }
        } else {
            ajaxResult.isError();
            ajaxResult.put("code", 500);
            ajaxResult.put("msg", "入库失败");
        }
        return ajaxResult;
    }
    @PostConstruct
    public void initializeTcpServer() throws InterruptedException {
        // 当系统名称为电子围栏且支持TCP协议时，开始进行TCP长连接服务端操作
        if (SYSTEM_NAME.equals("ef") && SYSTEM_TRANSPORT_PROTOCOL.contains("TCP")) {
            TimeUnit.SECONDS.sleep(30);
            /****************************TCP长连接服务端操作***************************************/
            if (MainObject.tcpServer == null) {
                System.out.println("TCP长连接服务端操作");
                MainObject.tcpServer = new AsyncTcpServer();
                System.out.println(SYSTEM_TCPSERVICEIP);
                System.out.println(SYSTEM_TCPSERVICEPORT);

                MainObject.tcpServer.initServer(SYSTEM_TCPSERVICEIP, SYSTEM_TCPSERVICEPORT, 1024);
                MainObject.tcpServer.launchServer();
            }

            // 异步调用 analysisUpFrame 方法
            CompletableFuture.runAsync(() -> agreementAnalysis2.analysisUpFrame());
        }
    }




    private boolean pingDevice(String ipAddress) {
        try {
            InetAddress address = InetAddress.getByName(ipAddress);
            return address.isReachable(5000); // 设置超时时间为5000毫秒
        } catch (Exception e) {
            return false;
        }
    }


//


}


